package com.geezdata.cps.base.aop;

import org.apache.commons.lang3.ClassUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.geezdata.cps.base.request.BaseRequest;
import com.geezdata.cps.base.utils.JsonUtil;

@Aspect
@Order(1)
@Component
public class RequestInterceptor {
    private static Logger logger = LoggerFactory.getLogger(RequestInterceptor.class);
    
    @Before("execution(* com.geezdata.cps.*.api.controller.*Controller.*(..))")
    public void request(JoinPoint mi) throws Throwable {
    	String methodSimpleInfo = getMethodSimpleName(mi);
    	
    	Object[] args = mi.getArgs();
    	if (args == null || args.length == 0) {
    		return;
    	}
    	
    	Object arg = args[0];
    	if(!(arg instanceof BaseRequest)) {
    		return;
    	}
    	
    	BaseRequest request = (BaseRequest) arg;
    	SecurityManager sm = ThreadContext.getSecurityManager();
    	if(sm == null ) {
    		logger.debug("Call={} Request={}", methodSimpleInfo, JsonUtil.toJson(request));
    		return ;
    	}
		
		Subject currentUser = SecurityUtils.getSubject();
		if (request == null || currentUser == null) {
			logger.debug("Call={} Request={} CurrentUser={}", methodSimpleInfo, JsonUtil.toJson(request), currentUser);
			return;
		}
		
		String userName = (String) currentUser.getPrincipal();
		logger.debug("Call={} Request={} CurrentUser={}", methodSimpleInfo, JsonUtil.toJson(request), userName);
		request.setCurrentUser(userName);
    }
    
    private static String getMethodSimpleName(JoinPoint mi) {
        return new StringBuilder(ClassUtils.getSimpleName(mi.getThis().getClass())).append(".")
                .append(mi.getTarget()).toString();
    }
}